var tetrisGame = (function (idDisplayInsLoc, idContorlerInsLoc, sNewIdName, jQ) {
    var speed = 400;
    var nScore = 0;
    var bIsContinue = true;
    var nTableSizeX = 11, nTableSizeY=22;   //从0计,隐藏3行做渐出
    var nBoxLocX = 6, nBoxLocY = 2;               
    var aBox = [[0, 0], [0, 0], [0, 0], [0, 0]];
    var aBoxOutline = [[0, 0], [0, 0], [0, 0], [0, 0]];
    var aBoxOutlineNext;
    var tbTable1;
    var oTimeCount;

    var bKeydownListened = false;
    var idTable1 = sNewIdName + "Table1";
    var idTable2 = sNewIdName + "Table2";
    var idBut1 = sNewIdName + "But1";
    var idSpeed = sNewIdName + "Speed";
    var idScore = sNewIdName + "Score";
    var Tetris = {
        init : function(){
            var that = this; 
            jQ(document).ready(function () {
                that.fCreateTable(nTableSizeX, nTableSizeY);
                that.fCreateControlKey();
                tbTable1 = jQ("#" + idTable1)[0];
                jQ(":radio:eq(1)").click(function () {
                    speed = 200;
                    jQ("#" + idSpeed).text(1000 / speed);
                    this.blur();
                });
                jQ(":radio:eq(0)").click(function () {
                    speed = 400;
                    jQ("#" + idSpeed).text(1000 / speed);
                    this.blur();
                });
                jQ("#" + idBut1).click(function () {
                    if (jQ("#" + idBut1).text() == "开始") {
                        jQ("#" + idBut1).text("重新开始");
                    } else {
                        jQ("#" + idScore).text("0");
                        jQ("#" + idSpeed).text(1000 / speed);
                        jQ("td:contains(囧)").text("");
                        bIsContinue = true;
                        for (i = 0; i <= nTableSizeY; i++) {
                            var row = tbTable1.rows[i];
                            for (j = 0; j <= nTableSizeX; j++) {
                                var cell = row.cells[j];
                                cell.isOccupy = false;
                                cell.style.backgroundColor = "#808080";
                            }
                        }
                    }                            
                    this.blur();
                    that.fCreateBox(true);
                    that.fTimeCount();
                });
                //jQ("#bnLeft").click(function () { fDoNextMovement(-1, 0); });
                //jQ("#bnRight").click(function () { fDoNextMovement(1, 0); });
                //jQ("#bnImmediatelyDown").click(function () { fImmediatelyDown(); });
                //jQ("#bnFastDown").click(function () { fFastDown(); });
                //jQ("#bnRotate").click(function () { fRotateBox(); });
            });
        },
                   
        fCreateTable:function (x, y) {
            var aHtml = [];
            var aHtml2 = [];
            var sHtml = "";
            for (var i = 0; i <= y; i++) {
                aHtml.push("<tr>");
                for (var j = 0; j <= x; j++) {
                    aHtml.push("<td></td>");
                }
                aHtml.push("</tr>");
            }
            for (var i = 0; i < 7; i++) {
                aHtml2.push("<tr>");
                for (var j = 0; j < 5; j++) {
                    aHtml2.push("<td></td>");
                }
                aHtml2.push("</tr>");
            }

            sHtml = "<table id = '" + idTable1 + "'><tbody>" + aHtml.join("") + "</tbody></table>" + "<table id = '" + idTable2 + "'><tbody>" + aHtml2.join("") + "</tbody></table>";
            
           
            jQ("#" + idDisplayInsLoc).append(sHtml);
        },
        fCreateControlKey: function(){
                    
            var sHtml = "<button id='" + idBut1 + "'>开始</button>";
            sHtml +="<INPUT TYPE='radio' NAME='level' value='400' checked>慢<INPUT TYPE='radio' NAME='level' value='200'>快";
            sHtml += "<p>积分：<b id='" + idScore + "'>0</b></p>";
            sHtml += "<p>速度：<b id='" + idSpeed + "'>2.5</b>格/秒</p>";
            sHtml +="<p>← → ↑ ↓ SPACE</p>";
            jQ("#" + idContorlerInsLoc).append(sHtml);
        },
        fTimeCount: function () {
            var that = this;
            (!bKeydownListened) && (bKeydownListened = true) && that.fCheckInput(); // 只需要监听一次
            that.fDoNextMovement(0, 1);
            //fAddSpeed();
            if (bIsContinue == true) {
                clearTimeout(oTimeCount);
                oTimeCount = setTimeout(function () {
                    that.fTimeCount();
                }, speed);
            }                                   
        },
        fCreateBox : function (bFirstTime) {
            var nRotate;
            nBoxLocX = 6;
            nBoxLocY = 2;
            if (bFirstTime == true) {             
                aBoxOutlineNext = this.fGetRandomNum();
                nRotate = parseInt(3 * Math.random(),10);
                for (var i = 1; i <= nRotate; i++) {
                    this.fRotateBox(aBoxOutlineNext, false);
                }
            }
            for (var i = 0; i < 4; i++) {
                aBoxOutline[i][0] = aBoxOutlineNext[i][0];
                aBoxOutline[i][1] = aBoxOutlineNext[i][1];
            }
            aBoxOutline.nShape = aBoxOutlineNext.nShape;
            //生成下一个box:
            aBoxOutlineNext = this.fGetRandomNum();
            nRotate = parseInt(3 * Math.random());
            for (var i = 1; i <= nRotate; i++) {
                this.fRotateBox(aBoxOutlineNext, false);
            }           
            for (var i = 0; i < 4; i++){
                aBox[i][0] = aBoxOutline[i][0] + nBoxLocX;
                aBox[i][1] = aBoxOutline[i][1] + nBoxLocY;
            }           
            this.fRedraw("new", 0, 0);
            //for (var i = 1; i <= nRotate; i++) {
            //    fRotateBox(true);
            //}
            this.fDrawPreview();           
    },
    fDrawPreview: function () {
        tbTable2 = jQ("#"+idTable2)[0];
        jQ("#"+idTable2+" td:contains(囧)").text("");
        for (var i = 0; i < 4; i++) {       //需再加box边框坐标判定以使box出现在正中央。
            tbTable2.rows[aBoxOutlineNext[i][1] + 4].cells[aBoxOutlineNext[i][0] + 2].innerHTML = "囧";
        }
    },
    fGetRandomNum: function () {
        var nRandomNum;
        var aBoxShape;
        nRandomNum = parseInt(7 * Math.random(),10);
        aBoxShape = [
			[[0, 0], [0, -1], [-1, 0], [1, 0]],     // shapeT:
			[[0, 0], [0, -1], [1, -1], [-1, 0]],    //shapeInvertZ:
			[[0, 0], [0, -1], [-1, -1], [1, 0]],    //shapeZ:
			[[0, 0], [0, 1], [0, -1], [1, 1]],      //shapeL:
			[[0, 0], [0, 1], [0, -1], [-1, 1]],     //shapeInvertL:                   
			[[0, 0], [0, 1], [0, -1], [0, -2]],     // shapeI:           
			[[0, 0], [0, -1], [1, 0], [1, -1]],     //shapeO:   
        ][nRandomNum];
        aBoxShape.nShape = nRandomNum;
        return aBoxShape;
    },

    fCheckInput: function () {
        var that = this;
        jQ(document).keydown(function (e) {
            switch (e.keyCode) {
                case 37:    //left                     
                    that.fDoNextMovement(-1, 0);
                    break;
                case 38:    //up  
                    that.fRotateBox(aBoxOutline, true);
                    break;
                case 39:    //right                                                  
                    that.fDoNextMovement(1, 0);
                    break;
                case 40:    //down                       
                    if (bIsContinue == true) {
                        that.fFastDown();
                    }
                    break;
                case 32:    //space
                    if (bIsContinue == true) {
                        that.fImmediatelyDown();
                    }
                    break;
                default:
                    break;
            }
        });
    },
    fFastDown : function () {
        var bSlideResult = 0;
        if(bSlideResult != 1) {
            bSlideResult = this.fDoNextMovement(0, 1);
        }
    },
    fImmediatelyDown : function () {          
        var bSlideResult = 0;         
        while (bSlideResult != 1) {                
            bSlideResult = this.fDoNextMovement(0, 1);
        }           
    },
    fRotateBox : function (aWhichBoxShape,bIsShow) {
        var nTransit;
        var nSupposeNextX, nSupposeNextY;
        if (aWhichBoxShape.nShape != 6) {
            //aBoxSideLoc = fGetBoxSideLoc(aBox);
            for (var i = 0; i < 4; i++) {
                nSupposeNextX = -(aWhichBoxShape[i][1]) + nBoxLocX;
                nSupposeNextY = aWhichBoxShape[i][0] + nBoxLocY;
                if (0 > nSupposeNextX || nSupposeNextX > nTableSizeX ||
                    0 > nSupposeNextY || nSupposeNextY > nTableSizeY) {
                    return 0;
                }
                if (tbTable1.rows[nSupposeNextY].cells[nSupposeNextX].isOccupy == true){
                    return 0;
                }
            }
            for (var i = 0; i < 4; i++) {   //预先更新数组，fredraw()再更新显示
                nTransit = aWhichBoxShape[i][0];
                aWhichBoxShape[i][0] = -(aWhichBoxShape[i][1]);
                aWhichBoxShape[i][1] = nTransit;
            }
            if (bIsShow == true) {
                this.fRedraw("rotate", 0, 0);
            }
        }
    },
    fRedraw : function (sType, nX, nY) {
        var oPreXY;
        for (var i = 0; i < 4; i++) {
            oPreXY = tbTable1.rows[aBox[i][1]].cells[aBox[i][0]];
            oPreXY.innerHTML = "";
            oPreXY.style.backgroundColor = "#808080";
        }
        if (sType == "move") {
            nBoxLocX += nX;
            nBoxLocY += nY;
        }
        for (var i = 0; i < 4; i++) {
            if (sType == "rotate") {
                //搞错对象了，已移回frotatebox（）里，move的也可以移回相应函数
            }                
            aBox[i][0] = aBoxOutline[i][0] + nBoxLocX;
            aBox[i][1] = aBoxOutline[i][1] + nBoxLocY;
            oPreXY = tbTable1.rows[aBox[i][1]].cells[aBox[i][0]];
            oPreXY.innerHTML = "囧";
            var aColors = [
                "#b6ff00",
                "#ff6a00",
                "#fce808",
                "#3696f2",
                "#e50000",
                "#850ffb",
                "#99ebfa"
            ];
            oPreXY.style.backgroundColor = aColors[aBoxOutline.nShape];
        }
    },
        
    fSlideXY : function (nX, nY) {
        var oSupposeNextSlideXY;
        var nSupposeNextX, nSupposeNextY;
        for (var i = 0; i < 4; i++) {
            nSupposeNextY = aBox[i][1] + nY;
            nSupposeNextX = aBox[i][0] + nX;
            oSupposeNextSlideXY = tbTable1.rows[nSupposeNextY].cells[nSupposeNextX];
            if (oSupposeNextSlideXY.isOccupy != true) {
                continue; 
            }
            else if(nY==1) {
                return 1;   //着陆已堆砌的方块 
            }
            else{
                return 0;   //左右无法移动
            }
        }
        this.fRedraw("move", nX, nY);
            
    },
    fDoNextMovement : function (nX, nY) {      //先判断是否贴近边框，再模拟下一个位置是否重叠。
        var oPreXY;
        var aBoxSideLoc = this.fGetBoxSideLoc(aBox); //BigestX,SmallestX,BigestY,SmallestY
        var bSlideResult = 1;
        if (((nY == 1) && (aBoxSideLoc[2] < nTableSizeY)) ||
            ((nX == -1) && (aBoxSideLoc[1] > 0)) ||
            ((nX == 1) && (aBoxSideLoc[0] < nTableSizeX))) {
            bSlideResult = this.fSlideXY(nX, nY);
        }         
        if(nY == 1 && bSlideResult==1){
            for (var i = 0; i < 4; i++) {
                oPreXY = tbTable1.rows[aBox[i][1]].cells[aBox[i][0]];
                oPreXY.isOccupy = true;               
            }
            this.fCheckEliminate(aBoxSideLoc[3], aBoxSideLoc[2]);
            if (aBoxSideLoc[3] <= 3) {        //已隐藏3行，第4行为顶部
                //clearTimeout(oTimeCount);
                bIsContinue = false;
                alert("game over,bro!");
            } else {
                this.fCreateBox(false);
            }
        }
        return bSlideResult;
    },         
    fGetBoxSideLoc : function (aBox) {
        var aBoxSideLoc = [0, 30, 0, 30];    //BigestX,SmallestX,BigestY,SmallestY
        for (var i = 0; i < 4; i++) {
            if (aBox[i][0] > aBoxSideLoc[0]) { aBoxSideLoc[0] = aBox[i][0]; }
            if (aBox[i][0] < aBoxSideLoc[1]) { aBoxSideLoc[1] = aBox[i][0]; }
            if (aBox[i][1] > aBoxSideLoc[2]) { aBoxSideLoc[2] = aBox[i][1]; }
            if (aBox[i][1] < aBoxSideLoc[3]) { aBoxSideLoc[3] = aBox[i][1]; }
        }
        return aBoxSideLoc;
    },       
    fCheckEliminate:function (nMinBoxY,nMaxBoxY) {
        var oXY, oXYMovedown;
        var sBgcolorMovedown;
        var nPlusScore = -1;
        var bThisLineIsFull=false;
        for (var j = nMinBoxY; j <= nMaxBoxY; j++) {
            for (var i = 0; i <= nTableSizeX; i++) {
                oXY = tbTable1.rows[j].cells[i];
                if (oXY.isOccupy != true) {
                    break;
                } else if (i == nTableSizeX) {
                    bThisLineIsFull = true;
                }
            }
            if (bThisLineIsFull) {
                bThisLineIsFull = false;
                nPlusScore = nPlusScore + 2;
                for (var i = 0; i <= nTableSizeX; i++) {
                    oXY = tbTable1.rows[j].cells[i];
                    this.fSetOccupy(oXY, "#808080", false);                                                  
                }
                for (var i = (j-1); i > 0; i--) {   //当前j是消除的行，此处循环将j上面的box往下移
                    for (var k = 0; k <= nTableSizeX; k++) {
                        oXY = tbTable1.rows[i].cells[k];
                        oXYMovedown = tbTable1.rows[i + 1].cells[k];
                        if (oXY.isOccupy == true) {
                            sBgcolorMovedown = oXY.style.backgroundColor;
                            this.fSetOccupy(oXY, "#808080", false);
                            this.fSetOccupy(oXYMovedown, sBgcolorMovedown, true);
                        }
                    }
                }
            }
        }
        if (nPlusScore == -1) { nPlusScore = 0; }
        else {
            speed -= 5;
            nScore += nPlusScore;
            jQ("#" + idScore).text(nScore);
            jQ("#"+idSpeed).text(1000/speed);
        }            
    },
    fSetOccupy: function (cell, sBgcolor, bIsOccupy) {              
        cell.isOccupy = bIsOccupy;                            
        cell.innerHTML = bIsOccupy?"囧":"";
        cell.style.backgroundColor = sBgcolor;
    }
    };//Tetris={            
    return {
        gameInit:function(){
            Tetris.init();
        }
    }
})("dvGameDisplayZoom","dvFunction","tb",$);//(function(){
        